use serde::{Deserialize, Serialize};
use serde_json::{self, Value};
use std::collections::HashMap;

/// 工具类 `BeanUtil` 用于处理对象属性的复制和转换
pub struct BeanUtil;

impl BeanUtil {
    /// 将一个对象的属性复制到另一个对象中
    ///
    /// # 参数
    /// * `source` - 源对象
    /// * `target` - 目标对象
    ///
    /// # 返回值
    /// 返回包含复制后的目标对象的 `Result<U, Box<dyn std::error::Error>>`
    pub fn copy_properties<T, U>(source: &T, target: &mut U) -> Result<(), Box<dyn std::error::Error>>
    where
        T: Serialize,
        U: for<'de> Deserialize<'de> + Serialize,
    {
        let source_json = serde_json::to_value(source)?;
        let target_json = serde_json::to_value(&*target)?;

        let merged_json = BeanUtil::merge_json(target_json, source_json);

        *target = serde_json::from_value(merged_json)?;

        Ok(())
    }

    /// 将一个对象的列表复制到另一个对象的列表中
    ///
    /// # 参数
    /// * `source_list` - 源对象列表
    ///
    /// # 返回值
    /// 返回包含目标对象列表的 `Result<Vec<U>, Box<dyn std::error::Error>>`
    pub fn copy_to_list<T, U>(source_list: &[T]) -> Result<Vec<U>, Box<dyn std::error::Error>>
    where
        T: Serialize,
        U: for<'de> Deserialize<'de>,
    {
        let json_string = serde_json::to_string(source_list)?;
        let target_list: Vec<U> = serde_json::from_str(&json_string)?;
        Ok(target_list)
    }

    /// 将一个对象转换为 HashMap
    ///
    /// # 参数
    /// * `obj` - 源对象
    ///
    /// # 返回值
    /// 返回包含属性的 `Result<HashMap<String, Value>, Box<dyn std::error::Error>>`
    pub fn bean_to_map<T>(obj: &T) -> Result<HashMap<String, Value>, Box<dyn std::error::Error>>
    where
        T: Serialize,
    {
        let json_value = serde_json::to_value(obj)?;
        let map = serde_json::from_value(json_value)?;
        Ok(map)
    }

    /// 将一个 HashMap 转换为对象
    ///
    /// # 参数
    /// * `map` - 属性的 HashMap
    ///
    /// # 返回值
    /// 返回包含对象的 `Result<T, Box<dyn std::error::Error>>`
    pub fn map_to_bean<T>(map: HashMap<String, Value>) -> Result<T, Box<dyn std::error::Error>>
    where
        T: for<'de> Deserialize<'de>,
    {
        let json_value = serde_json::to_value(map)?;
        let obj = serde_json::from_value(json_value)?;
        Ok(obj)
    }

    /// 合并两个 JSON 对象，将 source 的属性合并到 target 中
    pub fn merge_json(mut target: Value, source: Value) -> Value {
        if let Value::Object(target_map) = &mut target {
            if let Value::Object(source_map) = source {
                for (k, v) in source_map {
                    target_map.insert(k, v);
                }
            }
        }
        target
    }
}


fn main() -> Result<(), Box<dyn std::error::Error>> {
    #[derive(Clone, Serialize, Deserialize, Debug)]
    struct SourceStruct {
        id: i32,
        name: String,
        email: String,
    }

    #[derive(Clone, Serialize, Deserialize, Debug, Default)]
    struct TargetStruct {
        id: i32,
        name: String,
        phone: String,
    }

    let source = SourceStruct {
        id: 1,
        name: "Alice".to_string(),
        email: "alice@example.com".to_string(),
    };

    let mut target = TargetStruct {
        id: 0,
        name: "".to_string(),
        phone: "123-456-7890".to_string(),
    };

    BeanUtil::copy_properties(&source, &mut target)?;

    log::info!("Updated target: {:?}", target);

    let source_list = vec![
        SourceStruct {
            id: 2,
            name: "Bob".to_string(),
            email: "bob@example.com".to_string(),
        },
        SourceStruct {
            id: 3,
            name: "Charlie".to_string(),
            email: "charlie@example.com".to_string(),
        },
    ];

    let target_list: Vec<TargetStruct> = BeanUtil::copy_to_list(&source_list)?;
    log::info!("Copied list: {:?}", target_list);

    Ok(())
}